package jspwiki.plugins;

import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Map;

import org.apache.log4j.Logger;

import com.ecyrd.jspwiki.WikiContext;
import com.ecyrd.jspwiki.WikiEngine;
import com.ecyrd.jspwiki.plugin.PluginException;
import com.ecyrd.jspwiki.plugin.WikiPlugin;

/**
 * Dynamically execute a plugin from an attachment jar. plugin parameter has a
 * format of:
 * 
 * page/attachment.ext:plugin.full.classname
 * (Main/jspwiki-plugins.jar:jspwiki.plugins.HeaderPlugin)
 * 
 * @author Francis Novilla
 */
public class DynamicPlugin implements WikiPlugin {

  private static final Logger log = Logger.getLogger(DynamicPlugin.class);

  public static final String PARAM_PLUGIN = "p";

  /**
   * {@inheritDoc}
   */
  @SuppressWarnings("unchecked")
  public String execute(WikiContext context, Map params) throws PluginException {

    String result = null;

    String plugin = (String) params.get(PARAM_PLUGIN);
    String[] parms = plugin.split(":");
    try {
      WikiEngine engine = context.getEngine();

      String url = engine.getURL(WikiContext.ATTACH, parms[0], null, true);
      log.debug("url=" + url);

      addURL(new URL(url));
      Class classToLoad = Class.forName(parms[1]);
      WikiPlugin instance = (WikiPlugin) classToLoad.newInstance();
      result = instance.execute(context, params);
    } catch (Exception e) {
      log.error(e.getMessage(), e);
      throw new PluginException(e.getMessage(), e);
    }
    return result;
  }

  /**
   * @see http 
   *      ://stackoverflow.com/questions/60764/how-should-i-load-jars-dynamically
   *      -at-runtime
   */
  private void addURL(URL u) throws Exception {
    URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
    Class sysclass = URLClassLoader.class;
    Method method = sysclass.getDeclaredMethod("addURL", new Class[] { URL.class });
    method.setAccessible(true);
    method.invoke(sysloader, new Object[] { u });
  }

}
